﻿using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using Common.ParameterLocator;
using SpecFlowTfsLinker.Entities;

namespace SpecFlowTfsLinker.Parser
{
    [Serializable]
    public static class TestCaseParser
    {
        public static TestCase Create(string testCaseName, string testCaseStatement)
        {
            var regex = new Regex(ServiceParameter.Instance.Parameter.RegexFindStatement,
                                  RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
            var results = regex.Matches(testCaseStatement);

            var builder = TestCase.Builder;

            var currentType = StatementType.Given;
            foreach (var statement in from object result in results select result.ToString())
            {
                BuildStatement(statement, builder, ref currentType);
            }

            return builder.Name(testCaseName).Build();
        }

        private static void BuildStatement(string statement, TestCase.BuilderTestCase builder,
                                           ref StatementType currentType)
        {
            if (IsGivenOrAndGiven(statement, currentType))
            {
                currentType = StatementType.Given;
                builder.Given(statement);
                return;
            }
            if (IsWhenOrAndWhen(statement, currentType))
            {
                currentType = StatementType.When;
                builder.When(statement);
                return;
            }
            if (IsThenOrAndThen(statement, currentType))
            {
                currentType = StatementType.Then;
                builder.Then(statement);
                return;
            }
        }

        private static bool IsGivenOrAndGiven(string statement, StatementType currentType)
        {
            return IsGiven(statement) || IsAnd(statement) && currentType == StatementType.Given;
        }

        private static bool IsWhenOrAndWhen(string statement, StatementType currentType)
        {
            return IsWhen(statement) || IsAnd(statement) && currentType == StatementType.When;
        }

        private static bool IsThenOrAndThen(string statement, StatementType currentType)
        {
            return IsThen(statement) || IsAnd(statement) && currentType == StatementType.Then;
        }

        private static bool IsGiven(string statement)
        {
            return StartWith(statement, StatementType.Given);
        }

        private static bool IsWhen(string statement)
        {
            return StartWith(statement, StatementType.When);
        }

        private static bool IsThen(string statement)
        {
            return StartWith(statement, StatementType.Then);
        }

        private static bool IsAnd(string statement)
        {
            return StartWith(statement, StatementType.And);
        }

        private static bool StartWith(string statement, StatementType statementType)
        {
            return statement.StartsWith(statementType.ToString(), true, Thread.CurrentThread.CurrentCulture);
        }
    }
}